﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using CoreEx.Database.Query.Expressions;

namespace CoreEx.Database.Linq
{
    /// <summary>
    /// Represents the result of translating an <see cref="Expression"/> tree.
    /// </summary>
    public class TranslateResult
    {
        private readonly IDictionary<string, int> 
            _columnNames = new Dictionary<string, int>(); 
        
        /// <summary>
        /// Initializes a new instance of the <see cref="TranslateResult"/> class.
        /// </summary>
        public TranslateResult()
        {
            MemberResults = new Dictionary<MemberInfo, TranslateResult>();
            TableSources = new Dictionary<MemberInfo, TableSource>();
        }

        /// <summary>
        /// Gets or sets the name of the connection.
        /// </summary>        
        public string ConnectionName { get; set; }
   

        /// <summary>
        /// Gets or sets the <see cref="Type"/> that gets projected from this <see cref="TranslateResult"/>.
        /// </summary>
        public Type ProjectedType { get; set; }

        
        /// <summary>
        /// Gets or sets the <see cref="DbExpression"/> 
        /// </summary>
        public DbQuery<DbSelectExpression> SelectQuery { get; set; }


        /// <summary>
        /// Gets a list of <see cref="TranslateResult"/> instances that represents 
        /// the enumerable members of the <see cref="ProjectedType"/>.
        /// </summary>
        public IDictionary<MemberInfo, TranslateResult> MemberResults { get; private set; }

        /// <summary>
        /// Gets a list of <see cref="TableSource"/> instances that represents 
        /// all the table sources within the current query.
        /// </summary>
        public IDictionary<MemberInfo, TableSource> TableSources { get; private set; }


        /// <summary>
        /// Gets or sets the <see cref="TableSource"/> that represents the root table 
        /// in the <see cref="SelectQuery"/>.
        /// </summary>
        public TableSource RootTableSource { get; set; }


        /// <summary>
        /// Gets a unique column based on the supplied <paramref name="columnName"/>
        /// </summary>
        /// <param name="columnName">The column name for which to return a unique column name.</param>
        /// <returns><see cref="string"/></returns>        
        public string GetUniqueColumnName(string columnName)
        {
            if (!_columnNames.ContainsKey(columnName))
            {
                _columnNames.Add(columnName, 1);
                return columnName;
            }

            _columnNames[columnName]++;
            return string.Format("{0}{1}", columnName, _columnNames[columnName]);
        }

        public override string ToString()
        {
            if (!SelectQuery.IsNull())
                return SelectQuery.ToString();
            return base.ToString();
        }


        public LambdaExpression Projection { get; set; }
    }
}
